﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Miris.HumanMilkAnalyser.DataModel;
using Miris.HumanMilkAnalyser.Service;
using Miris.HumanMilkAnalyser.WPF.Model;

namespace Miris.HumanMilkAnalyser.WPF.ViewModel
{
    public class AnalysisResultSummaryViewModel : AnalysisResultViewModel
    {
        /// <summary>
        /// Initializes a new instance of the AnalysisResultSummaryViewModel class.
        /// </summary>
        public AnalysisResultSummaryViewModel(IDataService dataService)
            : base(dataService) { }

        public override void ResetProperties()
        {
            try
            {
                base.ResetProperties();
                InitializePredefinedDiagnosticMessageList();
            }
            catch (Exception ex)
            {
                RequestDisplayErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// The <see cref="IncludeBreastfeedingSignificance" /> property's name.
        /// </summary>
        public const string IncludeBreastfeedingSignificancePropertyName = "IncludeBreastfeedingSignificance";

        private bool _includeBreastfeedingSignificance = false;

        /// <summary>
        /// Sets and gets the IncludeBreastfeedingSignificance property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public bool IncludeBreastfeedingSignificance
        {
            get
            {
                return _includeBreastfeedingSignificance;
            }

            set
            {
                if (_includeBreastfeedingSignificance == value)
                {
                    return;
                }

                RaisePropertyChanging(IncludeBreastfeedingSignificancePropertyName);
                _includeBreastfeedingSignificance = value;
                RaisePropertyChanged(IncludeBreastfeedingSignificancePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="PredefinedDiagnosticMessageList" /> property's name.
        /// </summary>
        public const string PredefinedDiagnosticMessageListPropertyName = "PredefinedDiagnosticMessageList";

        private ObservableCollection<DiagnosticMessageReference> _predefinedDiagnosticMessageList = new ObservableCollection<DiagnosticMessageReference>();

        /// <summary>
        /// Sets and gets the PredefinedDiagnosticMessageList property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<DiagnosticMessageReference> PredefinedDiagnosticMessageList
        {
            get
            {
                return _predefinedDiagnosticMessageList;
            }

            set
            {
                if (_predefinedDiagnosticMessageList == value)
                {
                    return;
                }

                RaisePropertyChanging(PredefinedDiagnosticMessageListPropertyName);
                _predefinedDiagnosticMessageList = value;
                RaisePropertyChanged(PredefinedDiagnosticMessageListPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="SelectedDiagnosticMessageList" /> property's name.
        /// </summary>
        public const string SelectedDiagnosticMessageListPropertyName = "SelectedDiagnosticMessageList";

        private ObservableCollection<DiagnosticMessageReference> _selectedDiagnosticMessageList = new ObservableCollection<DiagnosticMessageReference>();

        /// <summary>
        /// Sets and gets the SelectedDiagnosticMessageList property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<DiagnosticMessageReference> SelectedDiagnosticMessageList
        {
            get
            {
                return _selectedDiagnosticMessageList;
            }

            set
            {
                if (_selectedDiagnosticMessageList == value)
                {
                    return;
                }

                RaisePropertyChanging(SelectedDiagnosticMessageListPropertyName);
                _selectedDiagnosticMessageList = value;
                RaisePropertyChanged(SelectedDiagnosticMessageListPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="AttachedDiagnosticMessage" /> property's name.
        /// </summary>
        public const string AttachedDiagnosticMessagePropertyName = "AttachedDiagnosticMessage";

        private string _attachedDiagnosticMessage = string.Empty;

        /// <summary>
        /// Sets and gets the AttachedDiagnosticMessage property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string AttachedDiagnosticMessage
        {
            get
            {
                return _attachedDiagnosticMessage;
            }

            set
            {
                if (_attachedDiagnosticMessage == value)
                {
                    return;
                }

                RaisePropertyChanging(AttachedDiagnosticMessagePropertyName);
                _attachedDiagnosticMessage = value;
                RaisePropertyChanged(AttachedDiagnosticMessagePropertyName);
            }
        }

        private RelayCommand<DiagnosticMessageReference> _addDiagnosticMessageCommand;

        /// <summary>
        /// Gets the AddDiagnosticMessage.
        /// </summary>
        public RelayCommand<DiagnosticMessageReference> AddDiagnosticMessageCommand
        {
            get
            {
                return _addDiagnosticMessageCommand ?? (_addDiagnosticMessageCommand = new RelayCommand<DiagnosticMessageReference>(
                    ExecuteAddDiagnosticMessageCommand,
                    CanExecuteAddDiagnosticMessageCommand));
            }
        }

        private void ExecuteAddDiagnosticMessageCommand(DiagnosticMessageReference parameter)
        {
            PredefinedDiagnosticMessageList.Remove(parameter);
            SelectedDiagnosticMessageList.Insert(0, parameter);
        }

        private bool CanExecuteAddDiagnosticMessageCommand(DiagnosticMessageReference parameter)
        {
            return parameter == null ? false : true;
        }

        private RelayCommand<DiagnosticMessageReference> _removeDiagnosticMessageCommand;

        /// <summary>
        /// Gets the RemoveDiagnosticMessageCommand.
        /// </summary>
        public RelayCommand<DiagnosticMessageReference> RemoveDiagnosticMessageCommand
        {
            get
            {
                return _removeDiagnosticMessageCommand ?? (_removeDiagnosticMessageCommand = new RelayCommand<DiagnosticMessageReference>(
                    ExecuteRemoveDiagnosticMessageCommand,
                    CanExecuteRemoveDiagnosticMessageCommand));
            }
        }

        private void ExecuteRemoveDiagnosticMessageCommand(DiagnosticMessageReference parameter)
        {
            SelectedDiagnosticMessageList.Remove(parameter);
            PredefinedDiagnosticMessageList.Insert(0, parameter);
        }

        private bool CanExecuteRemoveDiagnosticMessageCommand(DiagnosticMessageReference parameter)
        {
            return parameter == null ? false : true;
        }

        private RelayCommand _finishCommand;

        /// <summary>
        /// Gets the FinishCommand.
        /// </summary>
        public RelayCommand FinishCommand
        {
            get
            {
                return _finishCommand
                    ?? (_finishCommand = new RelayCommand(ExecuteFinishCommand));
            }
        }

        private void ExecuteFinishCommand()
        {
            try
            {
                // Add selected diagnostic message.
                foreach (var diagnosticMessage in SelectedDiagnosticMessageList)
                {
                    CurrentAnalysisResult.AnalysisResultDiagnosticMessages.Add(new AnalysisResultDiagnosticMessage
                    {
                        SampleNumber = CurrentAnalysisResult.SampleNumber,
                        MessageContent = diagnosticMessage.MessageContent
                    });
                }

                CurrentAnalysisResult.AttachedDiagnosticMessage = AttachedDiagnosticMessage.Trim();

                // Add the analysis result
                ServiceFactory.CreateAnalysisResultService().Add(CurrentAnalysisResult);

                // Send ReturnHomeMessage to PageBase.
                Messenger.Default.Send<int>(0, MainViewModel.ReturnHomeMessageToken);
            }
            catch (Exception ex)
            {
                RequestDisplayErrorMessage(ex.Message);
            }
        }

        /// <summary>
        /// Load the data from data source for initializing PredefinedDiagnosticMessageList. 
        /// </summary>
        private void InitializePredefinedDiagnosticMessageList()
        {
            var diagnosticMessageReferenceList = ServiceFactory.CreateDiagnosticMessageReferenceService().GetAll().OrderBy(m => m.OrderIndex);
            PredefinedDiagnosticMessageList = new ObservableCollection<DiagnosticMessageReference>(diagnosticMessageReferenceList);
        }
    }
}
